package com.dyson.jedis;

import redis.clients.jedis.Jedis;

import java.util.UUID;

/**
 * @Author: Wy
 * @Email: DysonWy@foxMail.com
 * @Time: 2020/3/2 17:52
 * @Description:
 */
public class JedisLock {

    private static final String lockPrefix = "redis:lock:";

    /**
     * @Author: Wy
     * @Param: [lockName, 锁key]
     * @Param: [lockName, 取锁时间,单位毫秒]
     * @Param: [lockName, 锁定时间,单位毫秒]
     * @Return: boolean
     * @Description:
     */
    public static boolean getLock(String lockName, Long getTimeOut, Long lockTime) {
        String lockKey = lockPrefix + lockName;
        String uniqueValue = UUID.randomUUID().toString();
        Jedis jedis = JedisPoolInstance.getJedisPool().getResource();
        long endTime = System.currentTimeMillis() + getTimeOut * 1000;
        try {
            int retryCount = 0;
            //时间段内获取锁,限制重试次数
            while (System.currentTimeMillis() < endTime && retryCount <= 3) {
                //取锁成功
                if (jedis.setnx(lockKey, uniqueValue) == 1) {//todo 这里设置key与过期时间不是原子操作
                    //设置过期
                    jedis.pexpire(lockKey, lockTime);
                    return true;
                }
                //当前服务宕机, 其他服务获取可设置过期
                if (jedis.ttl(lockKey) == -1) {
                    jedis.pexpire(lockKey, lockTime);
                }
                //未获取到锁,休眠后重试
                try {
                    Thread.sleep(100L);
                    ++retryCount;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return false;
        } finally {
            //资源释放
            jedis.close();
        }
    }

    public static boolean releaseLock(String lockName, String uniqueValue) {
        String lockKey = lockPrefix + lockName;
        Jedis jedis = JedisPoolInstance.getJedisPool().getResource();
        //获取锁value
        String value = jedis.get(lockKey);
        try {
            Long delResult = jedis.del(lockKey);
            if (delResult > 0) {
                return true;
            }
            //判断锁所有者是否符合
            /*if (value.equals(uniqueValue)) {
                //删除锁
                Long delResult = jedis.del(lockKey);
                if (delResult > 0) {
                    return true;
                }
            }*/
            return false;
        } finally {
            jedis.close();
        }

    }
}
